﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Text;

namespace Hsp.Auto.SQLite
{
    /// <summary>
    /// SQLite数据库帮助类
    /// SQLiteHelper
    /// Asp.Net Core NuGet引用SQLite
    /// System.Data.SQLite.Core
    /// V1.0.113.1
    /// </summary>
    public class DataHelper
    {
        #region 数据库连接

        public static string connectionString = string.Empty;

        /// <summary>
        /// 根据数据源、密码、版本号设置连接字符串。
        /// </summary>
        /// <param name="datasource">数据源。</param>
        /// <param name="password">密码。</param>
        /// <param name="version">版本号（缺省为3）。</param>
        public static void SetConnectionString(string datasource, string password, int version = 3)
        {
            connectionString = string.Format("Data Source={0};", datasource);
            connectionString += string.Format("Version={0};", version);
            if (!string.IsNullOrEmpty(password)) connectionString += string.Format("password={0}", password);
        }

        public static void SetConnectionString(string connString)
        {
            connectionString = connString;
        }

        #endregion

        public static string GetDbName()
        {
            var connstring = connectionString;
            if (string.IsNullOrEmpty(connstring)) return null;

            connstring = connstring[..connstring.LastIndexOf('.')];

            var dbName = string.Empty;
            var connArr = connstring.Split('\\');
            if (connArr.Length > 1)
            {
                dbName = connArr[^1];
            }
            else
            {
                connArr = connstring.Split('/');
                if (connArr.Length > 1)
                {
                    dbName = connArr[^1];
                }
            }

            return dbName;
        }


        #region 创建一个数据库文件。如果存在同名数据库文件，则会覆盖。

        /// <summary>
        /// 创建一个数据库文件。如果存在同名数据库文件，则会覆盖。
        /// </summary>
        /// <param name="dbName">数据库文件名。为null或空串时不创建。</param>
        /// <param name="password">（可选）数据库密码，默认为空。</param>
        /// <exception cref="Exception"></exception>
        public static void CreateDB(string dbName)
        {
            if (!string.IsNullOrEmpty(dbName))
            {
                try { SQLiteConnection.CreateFile(dbName); }
                catch (Exception) { throw; }
            }
        }

        #endregion

        #region 对SQLite数据库执行增删改操作，返回受影响的行数

        /// <summary>
        /// 对SQLite数据库执行增删改操作，返回受影响的行数。 
        /// </summary>
        /// <param name="sql">要执行的增删改的SQL语句。</param>
        /// <returns></returns>
        public int ExecuteNonQuery(string sql)
        {
            return this.ExecuteNonQuery(sql, new SQLiteParameter());
        }

        /// <summary> 
        /// 对SQLite数据库执行增删改操作，返回受影响的行数。 
        /// </summary> 
        /// <param name="sql">要执行的增删改的SQL语句。</param> 
        /// <param name="parameters">执行增删改语句所需要的参数，参数必须以它们在SQL语句中的顺序为准。</param> 
        /// <returns></returns> 
        /// <exception cref="Exception"></exception>
        public int ExecuteNonQuery(string sql, params SQLiteParameter[] parameters)
        {
            int affectedRows = 0;
            using (SQLiteConnection connection = new(connectionString))
            {
                using SQLiteCommand command = new(connection);
                try
                {
                    connection.Open();
                    command.CommandText = sql;
                    if (parameters.Length != 0)
                    {
                        command.Parameters.AddRange(parameters);
                    }
                    affectedRows = command.ExecuteNonQuery();
                }
                catch (Exception) { throw; }
            }
            return affectedRows;
        }

        /// <summary>
        /// 批量处理数据操作语句。
        /// </summary>
        /// <param name="list">SQL语句集合。</param>
        /// <exception cref="Exception"></exception>
        public void ExecuteNonQueryBatch(List<KeyValuePair<string, SQLiteParameter[]>> list)
        {
            using SQLiteConnection conn = new SQLiteConnection(connectionString);
            try { conn.Open(); }
            catch { throw; }
            using SQLiteTransaction tran = conn.BeginTransaction();
            using SQLiteCommand cmd = new SQLiteCommand(conn);
            try
            {
                foreach (var item in list)
                {
                    cmd.CommandText = item.Key;
                    if (item.Value != null)
                    {
                        cmd.Parameters.AddRange(item.Value);
                    }
                    cmd.ExecuteNonQuery();
                }
                tran.Commit();
            }
            catch (Exception) { tran.Rollback(); throw; }
        }

        #endregion

        #region 执行查询语句，并返回第一个结果

        /// <summary>
        /// 执行查询语句，并返回第一个结果。
        /// </summary>
        /// <param name="sql">查询语句。</param>
        /// <returns></returns>
        public object ExecuteScalar(string sql)
        {
            return this.ExecuteScalar(sql, new SQLiteParameter());
        }

        /// <summary>
        /// 执行查询语句，并返回第一个结果。
        /// </summary>
        /// <param name="sql">查询语句。</param>
        /// <returns>查询结果。</returns>
        /// <exception cref="Exception"></exception>
        public object ExecuteScalar(string sql, params SQLiteParameter[] parameters)
        {
            using SQLiteConnection conn = new(connectionString);
            using SQLiteCommand cmd = new(conn);
            try
            {
                conn.Open();
                cmd.CommandText = sql;
                if (parameters.Length != 0)
                {
                    cmd.Parameters.AddRange(parameters);
                }
                return cmd.ExecuteScalar();
            }
            catch (Exception) { throw; }
        }

        #endregion

        #region 执行一个查询语句，返回一个包含查询结果的DataTable

        /// <summary>
        /// 执行一个查询语句，返回一个包含查询结果的DataTable。
        /// </summary>
        /// <param name="sql">要执行的查询语句。</param>
        /// <returns></returns>
        public DataTable ExecuteQuery(string sql)
        {
            return this.ExecuteQuery(sql, new SQLiteParameter());
        }

        /// <summary> 
        /// 执行一个查询语句，返回一个包含查询结果的DataTable。 
        /// </summary> 
        /// <param name="sql">要执行的查询语句。</param> 
        /// <param name="parameters">执行SQL查询语句所需要的参数，参数必须以它们在SQL语句中的顺序为准。</param> 
        /// <returns></returns> 
        /// <exception cref="Exception"></exception>
        public DataTable ExecuteQuery(string sql, params SQLiteParameter[] parameters)
        {
            using SQLiteConnection connection = new(connectionString);
            using SQLiteCommand command = new(sql, connection);
            if (parameters.Length != 0)
            {
                command.Parameters.AddRange(parameters);
            }
            SQLiteDataAdapter adapter = new(command);
            DataTable data = new DataTable();
            try { adapter.Fill(data); }
            catch (Exception) { throw; }
            return data;
        }

        #endregion

        #region 执行一个查询语句，返回一个关联的SQLiteDataReader实例

        /// <summary>
        /// 执行一个查询语句，返回一个关联的SQLiteDataReader实例。
        /// </summary>
        /// <param name="sql">要执行的查询语句。</param>
        /// <returns></returns>
        public SQLiteDataReader ExecuteReader(string sql)
        {
            return ExecuteReader(sql, new SQLiteParameter());
        }

        /// <summary> 
        /// 执行一个查询语句，返回一个关联的SQLiteDataReader实例。 
        /// </summary> 
        /// <param name="sql">要执行的查询语句。</param> 
        /// <param name="parameters">执行SQL查询语句所需要的参数，参数必须以它们在SQL语句中的顺序为准。</param> 
        /// <returns></returns> 
        /// <exception cref="Exception"></exception>
        public SQLiteDataReader ExecuteReader(string sql, params SQLiteParameter[] parameters)
        {
            SQLiteConnection connection = new(connectionString);
            SQLiteCommand command = new(sql, connection);
            try
            {
                if (parameters.Length != 0)
                {
                    command.Parameters.AddRange(parameters);
                }
                connection.Open();
                return command.ExecuteReader(CommandBehavior.CloseConnection);
            }
            catch (Exception) { throw; }
        }

        #endregion

        #region 查询数据库中的所有数据类型信息

        /// <summary> 
        /// 查询数据库中的所有数据类型信息。
        /// </summary> 
        /// <returns></returns> 
        /// <exception cref="Exception"></exception>
        public DataTable GetSchema()
        {
            using SQLiteConnection connection = new(connectionString);
            try
            {
                connection.Open();
                return connection.GetSchema("TABLES");
            }
            catch (Exception) { throw; }
        }

        #endregion

        #region 执行一个查询语句，返回一个包含查询结果的DataSet

        /// <summary>
        /// 执行一个查询语句，返回一个包含查询结果的DataSet。
        /// </summary>
        /// <param name="sql">要执行的查询语句。</param>
        /// <returns></returns>
        public DataSet DataSetQuery(string sql)
        {
            return this.DataSetQuery(sql, new SQLiteParameter());
        }

        /// <summary> 
        /// 执行一个查询语句，返回一个包含查询结果的DataSet。 
        /// </summary> 
        /// <param name="sql">要执行的查询语句。</param> 
        /// <param name="parameters">执行SQL查询语句所需要的参数，参数必须以它们在SQL语句中的顺序为准。</param> 
        /// <returns></returns> 
        /// <exception cref="Exception"></exception>
        public DataSet DataSetQuery(string sql, params SQLiteParameter[] parameters)
        {
            using SQLiteConnection connection = new(connectionString);
            using SQLiteCommand command = new(sql, connection);
            if (parameters.Length != 0)
            {
                command.Parameters.AddRange(parameters);
            }
            SQLiteDataAdapter adapter = new(command);
            DataSet ds = new DataSet("ds");
            try { adapter.Fill(ds); }
            catch (Exception) { throw; }
            return ds;
        }

        #endregion


    }
}
